// const PENDING = Symbol('pending');
// const SUCCESS = Symbol('SUCCESS');
// const FAIL = Symbol('fail');

const PENDING = 'pending'; // 等待
const SUCCESS = 'SUCCESS'; // 成功
const FAIL = 'fail'; // 失败

class MyPromise {
    constructor(executor) {
        // 立刻执行函数，如果函数执行
        try {
            return executor(this.resolve, this.reject)
        } catch (e) {
            return this.reject(e);
        }

    }

    // // promsie 状态 
    status = PENDING;
    // // 成功之后的值
    value = undefined;
    // // 失败后的原因
    reason = undefined;
    // successCallback = data => data;
    // failCallback = reason => { throw reason };
    successCallback = [];
    failCallback = [];

    resolve = (data) => {
        if (this.status != PENDING) return false;
        this.status = SUCCESS;
        this.value = data;
        // return this.successCallback && this.successCallback(this.value);
        while (this.successCallback.length) {
            let callback = this.successCallback.shift();
            if (toString.call(callback) == '[object Function]') {
                callback();
            }
        }

    }

    reject = (reason) => {
        // 只有当pending的时候，才允许执行
        if (this.status != PENDING) return false;
        this.status = FAIL;
        this.value = reason;
        // return this.failCallback && this.failCallback(this.value);
        while (this.failCallback.length) {
            let callback = this.failCallback.shift();
            if (toString.call(callback) == '[object Function]') {
                callback();
            }
        }
    }

    then(successCallback, failCallback) {
        // 如果没有传递，给出默认值
        // this.successCallback = successCallback || this.successCallback;
        // this.failCallback = failCallback || this.failCallback;
        successCallback = successCallback || (value => value);
        failCallback = failCallback || (reason => { throw reason });
        let promise = new MyPromise((resolve, reject) => {
            try {
                if (this.status == SUCCESS) {
                    // 立刻执行成功
                    // 为了获取promise，因此通过setTimout延迟执行
                    setTimeout(() => {
                        resolvePromise(promise, successCallback(this.value), resolve, reject);
                    }, 0);
                    // successCallback && successCallback(this.value)
                } else if (this.status == FAIL) {
                    // 立刻执行失败
                    setTimeout(() => {
                        resolvePromise(promise, successCallback(this.value), resolve, reject);
                    }, 0);
                    // failCallback && failCallback(this.value);
                } else if (this.status == PENDING) {
                    // 有异步操作
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            resolvePromise(promise, successCallback(this.value), resolve, reject);
                        }, 0);
                    });
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            resolvePromise(promise, successCallback(this.value), resolve, reject);
                        }, 0);
                    });


                }
            } catch (e) {
                reject(e);
            }

        })

        return promise;

    }

    catch(failCallback) {
        return this.then.call(null, failCallback);
    }

    finally(callback) {
        return this.then(value => {
            return MyPromise.resolve(callback).then(() => value);
        }, reason => {
            return MyPromise.reject(callback).then(() => { throw reason });
        })
    }

    static all(arr) {
        let result = [];
        let index = 0;
        return new MyPromise((resolve, reject) => {
            function addResult(key, value) {
                result[key] = value;
                index++;
                if (index == arr.length) {
                    resolve(result);
                }
            }
            for (let i = 0; i < arr.length; i++) {
                let fn = arr[i];
                if (fn instanceof MyPromise) {
                    // 如果是promise异步对象
                    fn.then(value => addResult(i, value), reason => reject(reason))
                } else {
                    // 如果是立即执行
                    addResult(i, arr[i]);
                }
            }
        })
    }

    static race(arr) {
        return new MyPromise((resolve, reject) => {
            
            for (let i = 0; i < arr.length; i++) {
                let fn = arr[i];
                if (fn instanceof MyPromise) {
                    // 如果是promise异步对象
                    fn.then(value => resolve(value), reason => reject(reason))
                } else {
                    // 如果是立即执行
                    resolve(i, arr[i]);
                }
            }
        })
    }

    static resolve(value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value));
    }
    static reject(reason) {
        if (reason instanceof MyPromise) return reason;
        return new MyPromise((resolve, reject) => reject(reason));
    }
}

function resolvePromise(promise, x, resolve, reject) {
    // 判断promise 是否是 x  如果是，抛出异常
    if (promise == x) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // promise 对象
        x.then(resolve, reject);
    } else {
        // 普通值
        resolve(x);
    }
}


new MyPromise((resolve, reject) => {
    // resolve(1);
    // reject(2);
    // throw "!11";
    setTimeout(() => {
        console.log("测试异步");
        resolve(1);
    }, 2000)
    // setTimeout( () => {
    //     console.log("测试链式调用");
    //     resolve(1);
    // }, 2000)
}).then(data => {
    console.log(data);
    return { a: 1 };
}, data => {
    console.log(data);
    return { a: 2 }
}).then(data => {
    console.log(data);
});